package work;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class TestCase {
	private HashMap<String, String> trainingSet;
	private HashMap<String, String> LCMCSet;
	private XmlGenerator xmlGenerator;
	private ArrayList<NamedEntity> NrList;// 人名
	private ArrayList<NamedEntity> NtList;// 机构名
	private ArrayList<NamedEntity> NsList;// 地名
	private HashSet<RelationEntity> RelationSet;

	public TestCase(HashMap<String, String> training_set,
			XmlGenerator xml_generator) {
		trainingSet = training_set;
		xmlGenerator = xml_generator;
	}

	public TestCase(HashMap<String, String> training_set,
			HashMap<String, String> lcmc_set, XmlGenerator xml_generator) {
		trainingSet = training_set;
		LCMCSet = lcmc_set;
		xmlGenerator = xml_generator;
	}

	public void process(String filename) throws Exception {
		BufferedReader test_data = new BufferedReader(new InputStreamReader(
				new FileInputStream(filename), "gb2312"));
		String line = test_data.readLine();
		int line_num = 1;
		WordSeg ws = new WordSeg();
		while (line != null) {
			NrList = new ArrayList<NamedEntity>();
			NtList = new ArrayList<NamedEntity>();
			NsList = new ArrayList<NamedEntity>();
			RelationSet = new HashSet<RelationEntity>();
			String[] words = ws.segment(line);
			processNE(words, line_num);
			processRE(line_num);
			System.out.println("processing line " + line_num);
			++line_num;
			line = test_data.readLine();
		}
		test_data.close();
	}

	private void processNE(final String[] line, final int line_num) {
		int offset = 0;
		int sentence = 0;
		final int param = Param.MAX_MATCH;
		int max;
		String temp_str = null;
		System.out.println(line.length);
		for (int i = 0; i < line.length; ++i) {
			int j = i;
			max = Math.min(param, line.length - i);
			boolean found = false;
			NamedEntity best_match = null;
			if (line[i].equals("。") || line[i].equals("！")
					|| line[i].equals("？")) {
				++sentence;
				continue;
			}
			while (max > 0) {
				temp_str = rebuild(line, j, j + max);
				if (trainingSet.containsKey(temp_str)) {
					// match max number of words
					if (!found) {
						best_match = new NamedEntity(trainingSet.get(temp_str),
								temp_str, offset, sentence);
						xmlGenerator.appendNameEntity(best_match.type,
								best_match.text, line_num, offset);
						add2NEList(best_match);
						found = true;
					} else {
						NamedEntity sub_entity = new NamedEntity(
								trainingSet.get(temp_str), temp_str, offset,
								sentence, true);
						add2NEList(sub_entity);
					}
				}
				max--;
			}
			offset += line[i].length();
		}
	}

	private void add2NEList(NamedEntity ne) {
		if (ne.type.equals("nr")) {
			NrList.add(ne);
		} else if (ne.type.equals("nt")) {
			NtList.add(ne);
		} else if (ne.type.equals("ns")) {
			NsList.add(ne);
		}
	}

	private String rebuild(final String[] line, final int s, final int e) {
		String ans = "";
		for (int i = s; i < e; ++i) {
			ans += line[i];
		}
		return ans;
	}

	private void processRE(int line_num) {
		if (NrList == null || NtList == null || NsList == null
				|| RelationSet == null)
			return;
		processNtNs(line_num);
		// processNrNt(line_num);
		for (RelationEntity re : RelationSet) {
			appendRE(re);
		}
		RelationSet = null;
		NrList = NtList = NsList = null;
	}

	private void processNtNs(int line_num) {
		String relation = "located in";
		for (NamedEntity nt : NtList) {
			for (NamedEntity ns : NsList) {
				if (nt.text.indexOf(ns.text) != -1) {
					RelationSet.add(new RelationEntity(nt, ns, line_num,
							relation));
				} else if ((ns.start + ns.text.length()) == nt.start) {
					RelationSet.add(new RelationEntity(nt, ns, line_num,
							relation));
				} else if (utility.Text.containPrefixString(nt.text, ns.text,
						Param.MAX_PREFIX_CUT, Param.MIN_PREFIX_LENGHT)) {
					RelationSet.add(new RelationEntity(nt, ns, line_num,
							relation));
				}
			}
		}
	}

	private void processNrNt(int line_num) {
		String relation = "employee";
		for (NamedEntity nr : NrList) {
			for (NamedEntity nt : NtList) {
				if (nr.sentenceNum == nt.sentenceNum) {

					RelationSet.add(new RelationEntity(nr, nt, line_num,
							relation));
				}
			}
		}
	}

	private void appendRE(RelationEntity re) {
		xmlGenerator.appendRelation(re.type1, re.type2, re.text1, re.text2,
				re.doc, re.relation);
	}

}
